package main

import "fmt"

// 结构体
type address struct {
	province string
	city     string
}

// 结构体
type person struct {
	name string
	age  uint
	addr address
}

// 接口
type StringerImt interface {
	String() string
}

// person接口实现
func (p person) String() string {
	return fmt.Sprintf("the name is %s, age is %d", p.name, p.age)
}

// address实现接口
func (a address) String() string {
	return fmt.Sprintf("the addr is %s%s", a.province, a.city)
}

// 接口调用
func printString(s StringerImt) {
	fmt.Println(s.String())
}

// 工厂函数
func Newperson(name string) *person {
	return &person{name: name}
}

// 继承和组合
// go语言中没有继承的概念，所以结构体、接口之间也没有父子关系，go语言提倡的是组合，利用组合达到代码复用的目的，这也更灵活。
type Reader interface {
	Reader(p []byte) (n int, err error)
}
type Writer interface {
	Write(p []byte) (n int, err error)
}

// ReaderWriter接口是Reader和Writer的组合，组合后，ReaderWriter接口具有Reader和Writer中的所有方法，这样新接口ReaderWriter就不用定义自己的方法了，组合Reader和Writer的就可以了。
type ReaderWriter interface {
	Reader
	Writer
}

// 组合结构体
type person2 struct {
	name string
	age  uint
	address
}

func main() {
	//结构体赋值
	p := person{
		age:  30,
		name: "宋发元",
		addr: address{
			province: "浙江",
			city:     "杭州",
		},
	}
	//结构体调用
	fmt.Println(p.addr.province)

	//接口调用
	fmt.Println("************接口调用***********")
	printString(p)
	printString(&p)
	printString(p.addr)

	//工厂函数
	p1 := Newperson("张三")
	fmt.Println(p1)

	//组合
	p2 := person2{
		name: "宋发元",
		age:  30,
		address: address{
			province: "北京",
			city:     "北京",
		},
	}
	//像使用自己的字段一样，直接使用
	fmt.Println("组合：", p2.province)
}
